using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web;
using Wikey.Extensibility.Interfaces;
using Wikey.Interfaces.Attributes;

namespace Wikey.Transformation
{
    public class TransformationPluginLoader
    {
        public TransformationPluginLoader()
        {
            TransformerCollectionType = new Dictionary<string, Type>();
        }

        public TransformationPluginLoader Load()
        {
            LoadAssemblies();
            return this;
        }
        private void LoadAssembliesInPluginDirectory() {
            string pluginPath = HttpContext.Current.Server.MapPath("~/bin/Plugins");
            DirectoryInfo di = new DirectoryInfo(pluginPath);

            FileInfo[] pluginAssemblies = di.GetFiles("*.dll");

            foreach (var pluginAssembly in pluginAssemblies) {
                assemblies.Add(Assembly.LoadFile(pluginAssembly.FullName));
            }

        }
        private IEnumerable<Type> FindDerivedTypes(Assembly assembly, Type baseType) {
            try
            {
                return assembly.GetTypes().Where(baseType.IsAssignableFrom);               
            }
            catch( Exception ex )
            {
                ILogger logger = Factory.Get<ILogger>();
                logger.Error(String.Empty , ex );
                return null;
            }
        }

        private void LoadAssemblies() {
            LoadCurrentAssembly();
            LoadAssembliesInPluginDirectory();

            foreach (var assembly in assemblies) {
                var tranformerTypes = FindDerivedTypes(assembly, typeof(ITransformer));

                foreach (var type in tranformerTypes) {
                    foreach (var attribute in type.GetCustomAttributes(true)) {
                        if (attribute is TransformerAttribute) {
                            var value = attribute as TransformerAttribute;
                            TransformerCollectionType.Add(value.Command, type);
                        }
                    }
                }
            }
        }

        public readonly Dictionary<string, Type> TransformerCollectionType;

        private void LoadCurrentAssembly() {
            assemblies.Add(Assembly.GetExecutingAssembly());
        }

        List<Assembly> assemblies = new List<Assembly>(1);
      

    }
}